package com.txc.pay.alipayLife.utils;


import cn.hutool.core.util.StrUtil;
import com.jcraft.jsch.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import java.io.*;
import java.util.Properties;
import java.util.Vector;

@Component
public class SftpUtil {

    private static final Logger logger = LoggerFactory.getLogger(SftpUtil.class);

    private ChannelSftp sftp = null;

    private Session sshSession = null;
    @Value(value = "${lifePay.sftp.host}")
    public String host;
    @Value(value = "${lifePay.sftp.port}")
    public int port;

    @Value(value = "${lifePay.sftp.username}")
    public String usernameRoot;
    @Value(value = "${lifePay.sftp.password}")
    public String passwordRoot;

    public SftpUtil() {
        super();
    }

    public SftpUtil(String host, int port, String username, String password) {
        super();
        this.host = host;
        this.port = port;
        this.usernameRoot = username;
        this.passwordRoot = password;
    }

    /**
     * 连接sftp服务器
     *
     * @return ChannelSftp sftp连接实例
     */
    public ChannelSftp connect() {
        JSch jsch = new JSch();
        try {
            sshSession = jsch.getSession(usernameRoot, host, port);
            sshSession.setPassword(passwordRoot);
            Properties properties = new Properties();
            properties.put("StrictHostKeyChecking", "no");
            properties.put("PreferredAuthentications", "password");
            sshSession.setConfig(properties);
            sshSession.connect();
            Channel channel = sshSession.openChannel("sftp");
            channel.connect();
            sftp = (ChannelSftp) channel;
        } catch (JSchException e) {
            logger.error("sftp连接失败!{}", e.getMessage());
            throw new RuntimeException("sftp连接失败");
        }
        return sftp;
    }

    /**
     * 下载远程sftp服务器文件
     *
     * @param remotePath     远程路径
     * @param remoteFilename 远程文件名称
     * @param localFilename  本地存放路径
     * @return
     */
    public boolean downloadFile(String remotePath, String remoteFilename, String localPath, String localFilename)
            throws SftpException, IOException, Exception {
        FileOutputStream output = null;
        boolean success = false;
        try {
            File targetFile = new File(localPath);//本地目录不存在则创建
            if (!targetFile.exists()) {
                targetFile.mkdirs();
            }
            String localFilePath = localPath + File.separator + localFilename;
            File localFile = new File(localFilePath);
            // 有文件和下载文件重名
            if (localFile.exists()) {
                new File(localFilePath).delete();
                logger.info("文件: " + localFilePath + " 已经存在!");
            }
            output = new FileOutputStream(localFile);

            String file = remotePath + "/" + remoteFilename;
            sftp.get(file, output);
            success = true;
            logger.info("成功接收文件,本地路径：" + localFilePath);
        } catch (SftpException e) {
            logger.error("接收文件时SftpException异常!{}", e.getMessage());
            e.printStackTrace();
            return success;
        } catch (IOException e) {
            logger.error("接收文件时有I/O异常!{}", e.getMessage());
            return success;
        } finally {
            try {
                if (null != output) {
                    output.close();
                }
                // 关闭连接
                disconnect();
            } catch (IOException e) {
                logger.error("关闭文件时出错!{}", e.getMessage());
            }
        }
        return success;
    }


    public void downloadFile(String remotePath, String remoteFilename, OutputStream outputStream) {
        try {
            if (!remotePath.isEmpty()) {
                sftp.cd(remotePath);
            }
            sftp.get(remoteFilename, outputStream);
        } catch (Exception e) {
            throw new RuntimeException(e.getMessage());
        }
    }
    /**
     * 下载远程sftp服务器文件
     *
     * @param remotePath     远程路径
     * @param remoteFilename 远程文件名称
     * @return
     */
    public InputStream downloadFile(String remotePath, String remoteFilename) {
        try {
            if (!remotePath.isEmpty()) {
                sftp.cd(remotePath);
            }
            return sftp.get(remoteFilename);
        }catch (Exception e) {
            logger.error("接收文件时有I/O异常!{}", e.getMessage());
            throw new NullPointerException(e.getMessage());
        }
    }
    /**
     * 删除远程文件
     *
     * @param remotePath
     * @param remoteFilename
     * @return
     * @throws Exception
     */
    public boolean deleteFile(String remotePath, String remoteFilename) throws Exception {
        boolean success = false;
        try {
            // 更改服务器目录
            if (null != remotePath && !remotePath.trim().isEmpty()) {
                sftp.cd(remotePath);
            }
            // 删除文件
            sftp.rm(remoteFilename);
            System.err.println("删除远程文件" + remoteFilename + "成功!");
            success = true;
        } catch (SftpException e) {
            System.err.println("删除文件时有SftpException异常!");
            e.printStackTrace();
            System.err.println(e.getMessage());
            return false;
        } catch (Exception e) {
            System.err.println("删除文件时有异常!");
            System.err.println(e.getMessage());
            return false;
        } finally {
            // 关闭连接
            disconnect();
        }
        return true;
    }

    /**
     * 上传单个文件，如果指正下载文件名则使用，否则保留原有文件名
     *
     * @param remoteFilePath 远程文件路径 /tmp/xxx.txt ||xxx.txt.zip
     * @param uploadFilePath 要上传的文件 如：D:\\test\\xxx.txt
     * @throws SftpException
     * @throws FileNotFoundException
     */
    public void uploadFile(String remoteFilePath, String uploadFilePath) throws SftpException, FileNotFoundException {
        FileInputStream in = null;
        connect();

        try {
            sftp.cd(remoteFilePath);
        } catch (SftpException e) {
            e.printStackTrace();
            try {
//                sftp.mkdir(remoteFilePath);
                String[] dirs = remoteFilePath.split("/");
                String tempPath = "";
                int index = 0;
                mkdirDir(dirs, tempPath, dirs.length, index);
                sftp.cd(remoteFilePath);
            } catch (SftpException e1) {
                e1.printStackTrace();
                disconnect();
                throw new RuntimeException("ftp创建文件路径失败" + remoteFilePath);
            }
        }
        File file = new File(uploadFilePath);
        try {
            in = new FileInputStream(file);
            sftp.put(in, file.getName());
        } catch (FileNotFoundException e) {
            throw e;
        } catch (SftpException e) {
            throw e;
        } finally {
            if (in != null) {
                try {
                    in.close();
                } catch (IOException e) {
                }
            }
            disconnect();
        }
    }

    /**
     * 递归根据路径创建文件夹
     *
     * @param dirs     根据 / 分隔后的数组文件夹名称
     * @param tempPath 拼接路径
     * @param length   文件夹的格式
     * @param index    数组下标
     * @return
     */
    public void mkdirDir(String[] dirs, String tempPath, int length, int index) {
        // 以"/a/b/c/d"为例按"/"分隔后,第0位是"";顾下标从1开始
        index++;
        if (index < length) {
            // 目录不存在，则创建文件夹
            tempPath += "/" + dirs[index];
        }
        try {
            sftp.cd(tempPath);
            if (index < length) {
                mkdirDir(dirs, tempPath, length, index);
            }
        } catch (SftpException ex) {
            try {
                sftp.mkdir(tempPath);
                sftp.cd(tempPath);
            } catch (SftpException e) {
                e.printStackTrace();
            }

            mkdirDir(dirs, tempPath, length, index);
        }
    }

    public void uploadFile(String remoteFilePath, InputStream inputStream, String FileName) throws SftpException {
        FileInputStream in = null;
        connect();

        if (inputStream == null) throw new NullPointerException();
        if (FileName == null || StrUtil.isEmpty(FileName)) throw new NullPointerException();

        try {
            sftp.cd(remoteFilePath);
        } catch (SftpException e) {
            e.printStackTrace();
            try {
                sftp.mkdir(remoteFilePath);
                sftp.cd(remoteFilePath);
            } catch (SftpException e1) {
                e1.printStackTrace();
                disconnect();
                throw new RuntimeException("ftp创建文件路径失败 : " + remoteFilePath);
            }
        }
        try {
            sftp.put(inputStream, FileName);
        } catch (SftpException e) {
            throw e;
        } finally {
            if (in != null) {
                try {
                    in.close();
                } catch (IOException e) {
                }
            }
        }

        disconnect();
    }

    /**
     * 列出目录下的文件
     *
     * @param directory
     * @return
     * @throws SftpException
     */
    public Vector listFiles(String directory) throws SftpException {
        return sftp.ls(directory);
    }

    /**
     * 关闭连接
     */
    public void disconnect() {
        if (this.sftp != null) {
            if (this.sftp.isConnected()) {
                this.sftp.disconnect();
                this.sftp = null;
            }
        }
        if (this.sshSession != null) {
            if (this.sshSession.isConnected()) {
                this.sshSession.disconnect();
                this.sshSession = null;
            }
        }
    }

    public static void main11(String[] args) throws SftpException, IOException, Exception {
        SftpUtil sftpUtil = new SftpUtil();
        //连接
        sftpUtil.connect();

        //获取文件夹中文件列表
        Vector v = sftpUtil.listFiles("/download");
//        System.out.println(v);
        for (Object name : v) {
            if (name.toString().contains("50188")) {
                System.out.println(name.toString());
            }
        }
        //sftp下载文件
//        boolean flag = sftpUtil.downloadFile("/download", "ALIPAY_WTYBSNXQGSPSNEW_DSDZ_50188_20231218.txt", "C:\\Users\\tao\\Desktop", "alipay20231218.txt");
        sftpUtil.disconnect();
    }
}

